package com.hzy.fivepalace.wx.service;

import com.alibaba.fastjson2.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.hzy.fivepalace.common.type.CollectTypeEnums;
import com.hzy.fivepalace.common.util.ResponseUtil;
import com.hzy.fivepalace.common.util.TableDataInfo;
import com.hzy.fivepalace.db.dao.ex.CommentMapperEx;
import com.hzy.fivepalace.db.dao.ex.DtsCategoryMapperEx;
import com.hzy.fivepalace.db.dao.ex.DtsCouponUserMapperEx;
import com.hzy.fivepalace.db.dao.ex.DtsGoodsMapperEx;
import com.hzy.fivepalace.db.domain.*;
import com.hzy.fivepalace.db.service.*;
import com.hzy.fivepalace.db.vo.wx.*;
import com.hzy.fivepalace.wx.async.WxAsyncFactory;
import org.apache.commons.lang3.StringUtils;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * 商品服务
 */
@Service
public class WxGoodsService {

    private static final Logger logger = LoggerFactory.getLogger(WxGoodsService.class);

    @Resource
    private DtsCategoryMapperEx categoryMapper;

    private DtsCouponUserMapperEx couponUserMapperEx;

    @Autowired
    private DtsUserService userService;

    @Resource
    private DtsGoodsMapperEx goodsMapperEx;

    @Resource
    private Redisson redisson;

    @Autowired
    private DtsCollectService collectService;

    @Autowired
    private DtsGoodsService goodsService;

    @Resource
    private CommentMapperEx commentMapperEx;
    @Resource
    private WxAsyncFactory wxAsyncFactory;
    @Autowired
    private DtsGoodsSecurityService goodsSecurityService;
    @Autowired
    private DtsGoodsProductService productService;
    @Autowired
    private DtsLogisticsService logisticsService;
    @Resource
    private DtsGroupProductService groupProductService;
    @Resource
    private DtsGroupOpenListService groupOpenListService;

    private final static ArrayBlockingQueue<Runnable> WORK_QUEUE = new ArrayBlockingQueue<>(9);

    private final static RejectedExecutionHandler HANDLER = new ThreadPoolExecutor.CallerRunsPolicy();

    private static ThreadPoolExecutor executorService = new ThreadPoolExecutor(16, 16, 1000, TimeUnit.MILLISECONDS,
            WORK_QUEUE, HANDLER);


    /**
     * 小程序：首页类目列表
     *
     * @param page
     * @param size
     * @return
     */
    public TableDataInfo getCategoryList(Integer page, Integer size) {

        Page p = PageHelper.startPage(page, size);
        List<WxCategoryVo> list = categoryMapper.wxGetCategoryList();
        if (CollectionUtils.isEmpty(list)) {
            list = new ArrayList<>();
        }
        return TableDataInfo.getDataTable(list, p.getTotal());
    }

    /**
     * 获取小程序新分类
     *
     * @return
     */
    public Object getNewCategoryList() {
        List<WxNewCategoryVo> list=categoryMapper.wxGetNewCategoryList();
        if(CollectionUtils.isEmpty(list)){
            list=new ArrayList<>();
        }
        return ResponseUtil.ok(list);
    }


    /**
     * 根据类目id获取商品列表
     *
     * @param page
     * @param size
     * @param categoryId 类目ID
     * @param orderBy    0综合，1销量，2上市新品，3价格由低到高,4价格由高到低,默认为0
     * @return
     */
    public TableDataInfo getGoodsListByCategoryId(Integer page, Integer size, Integer categoryId, Integer orderBy) {
        Page p = PageHelper.startPage(page, size);
        List<WxGoodsListVo> list = goodsMapperEx.getGoodsListByCategoryId(categoryId, orderBy);
        if (CollectionUtils.isEmpty(list)) {
            list = new ArrayList<>();
        } else {
            list.forEach(goods -> {
                goods.setInventory(null == goods.getInventory() ? 0 : goods.getInventory());
                goods.setGoodsPrice(null == goods.getGoodsPrice() ? new BigDecimal("0") : goods.getGoodsPrice());
            });
        }
        return TableDataInfo.getDataTable(list, p.getTotal());
    }

    /**
     * 根据类目id获取所有商品列表
     * @param categoryId
     * @return
     */
    public Object getAllGoodsListByCategoryId(Integer categoryId) {
        List<WxGoodsListVo> list = goodsMapperEx.getGoodsListByCategoryId(categoryId, null);
        if (CollectionUtils.isEmpty(list)) {
            list = new ArrayList<>();
        } else {
            list.forEach(goods -> {
                goods.setInventory(null == goods.getInventory() ? 0 : goods.getInventory());
                goods.setGoodsPrice(null == goods.getGoodsPrice() ? new BigDecimal("0") : goods.getGoodsPrice());
            });
        }
        return ResponseUtil.ok(list);
    }

    /**
     * 商品搜索
     *
     * @param page
     * @param size
     * @param content
     * @param orderBy    排序方式:0综合，1销量，2上市新品，3价格由低到高,4价格由高到低,默认为0
     * @param categoryId
     * @return
     */
    public TableDataInfo goodsSearch(Integer page, Integer size, String content, Integer orderBy, Integer categoryId) {
        Page p = PageHelper.startPage(page, size);
        List<WxGoodsListVo> list = goodsMapperEx.goodsSearch(content, orderBy, categoryId);
        if (CollectionUtils.isEmpty(list)) {
            list = new ArrayList<>();
        } else {
            list.forEach(goods -> {
                goods.setInventory(null == goods.getInventory() ? 0 : goods.getInventory());
                goods.setGoodsPrice(null == goods.getGoodsPrice() ? new BigDecimal("0") : goods.getGoodsPrice());
            });
        }
        return TableDataInfo.getDataTable(list, p.getTotal());
    }

    /**
     * 热卖推荐
     *
     * @param userId
     * @param goodsId
     * @return
     */
    public Object sellingRecommend(Integer userId, Integer goodsId) {
        List<WxGoodsListVo> list = goodsMapperEx.sellingRecommend(goodsId, userId);
        if (CollectionUtils.isEmpty(list)) {
            list = new ArrayList<>();
        } else {
            list.forEach(goods -> {
                goods.setInventory(null == goods.getInventory() ? 0 : goods.getInventory());
                goods.setGoodsPrice(null == goods.getGoodsPrice() ? new BigDecimal("0") : goods.getGoodsPrice());
            });
        }
        return ResponseUtil.ok(list);
    }

    /**
     * 猜你喜欢
     *
     * @param userId
     * @param goodsId
     * @return
     */
    public Object guessYouLike(Integer userId, Integer goodsId) {
        List<WxGoodsListVo> list = goodsMapperEx.guessYouLike(goodsId, userId);
        if (CollectionUtils.isEmpty(list)) {
            list = new ArrayList<>();
        } else {
            list.forEach(goods -> {
                goods.setInventory(null == goods.getInventory() ? 0 : goods.getInventory());
                goods.setGoodsPrice(null == goods.getGoodsPrice() ? new BigDecimal("0") : goods.getGoodsPrice());
            });
        }
        return ResponseUtil.ok(list);
    }

    /**
     * 用户足迹
     *
     * @param page
     * @param size
     * @param userId   用户id
     * @param dataTime 日期：如2022-11-11
     * @return
     */
    public TableDataInfo getUserFootprint(Integer page, Integer size, Integer userId, String dataTime) {
        if (StringUtils.isBlank(dataTime)) {
            return TableDataInfo.errorDataTable("参数【dataTime】为空");
        }
        Page p = PageHelper.startPage(page, size);
        List<WxUserFootprint> list = goodsMapperEx.getUserFootprint(userId, dataTime);
        if (CollectionUtils.isEmpty(list)) {
            list = new ArrayList<>();
        }
        return TableDataInfo.getDataTable(list, p.getTotal());
    }


    /**
     * 小程序：获取用户收藏列表
     *
     * @param page
     * @param size
     * @return
     */
    public TableDataInfo getUserCollectionList(Integer page, Integer size, Integer userId) {
        Page p = PageHelper.startPage(page, size);
        List<WxGoodsListVo> list = goodsMapperEx.getUserCollectionList(userId);
        if (CollectionUtils.isEmpty(list)) {
            list = new ArrayList<>();
        } else {
            list.forEach(goods -> {
                goods.setInventory(null == goods.getInventory() ? 0 : goods.getInventory());
                goods.setGoodsPrice(null == goods.getGoodsPrice() ? new BigDecimal("0") : goods.getGoodsPrice());
            });
        }
        return TableDataInfo.getDataTable(list, p.getTotal());
    }

    /**
     * 用户收藏添加或删除
     * <p>
     * 如果商品没有收藏，则添加收藏；如果商品已经收藏，则删除收藏状态。
     *
     * @param userId
     * @param goodsId
     * @return
     */
    public Object addordeleteCollection(Integer userId, Integer goodsId) {
        RLock lock = redisson.getLock("user_addordeleteCollection_" + userId);
        if (lock.isLocked()) {
            return ResponseUtil.frequent();
        }
        lock.lock(30, TimeUnit.SECONDS);
        if (null == goodsId || goodsId < 1) {
            lock.unlock();
            return ResponseUtil.fail("参数【goodsId】为空");
        }
        Byte type = CollectTypeEnums.GOODS.getId();//商品收藏
        DtsCollect collect = collectService.queryByTypeAndValueIds(userId, type, goodsId);
        if (null != collect) {//存在就是取消收藏
            collect.setDeleted(true);
            collect.setUpdateTime(LocalDateTime.now());
            collectService.updateById(collect);
            lock.unlock();
            return ResponseUtil.ok("已取消收藏", null);
        } else {
            collect = new DtsCollect();
            collect.setDeleted(false);
            collect.setType(type);
            collect.setUserId(userId);
            collect.setValueId(goodsId);
            collectService.add(collect);
            lock.unlock();
            return ResponseUtil.ok("收藏成功", null);
        }
    }

    /**
     * 商品详情
     *
     * @param userId
     * @param goodsId
     * @return
     */
    public Object detail(Integer userId, Integer goodsId) {
        DtsUser user =null!=userId?userService.findById(userId):null;

        // 商品信息
        DtsGoods info = goodsService.selectById(goodsId);
        if (null == info) {
            return ResponseUtil.badArgument("商品不存在或已下架");
        }

        // 商品规格对应的数量和价格
        Callable<List<DtsGoodsProductService.specificationVo>> goodsProductsCallable = () -> productService.getGoodsProduct(goodsId,user,false, null);
        FutureTask<List<DtsGoodsProductService.specificationVo>> goodsProductsListTask = new FutureTask<>(goodsProductsCallable);
        executorService.submit(goodsProductsListTask);
        Map<String, Object> data = new HashMap<>();
        try {
            data.put("productList", goodsProductsListTask.get());//货品集合
        } catch (Exception e) {
            logger.error("获取商品规格出错-商品规格,商品id:{},msg:{}", goodsId, e.getMessage());
            return ResponseUtil.fail("获取商品规格出错");
        }


        //商品最低价格
        BigDecimal retailPrice = info.getRetailPrice();

        String price = null;

        //商品最高价格
        BigDecimal maxPrice = goodsService.getGoodsMaxPrice(goodsId);
        if (!StringUtils.equals(retailPrice.toString(), maxPrice.toString())) {//最高价格和最低价格不一样就拼接价格范围
            price = retailPrice.stripTrailingZeros().toPlainString() + "～" + maxPrice.stripTrailingZeros().toPlainString();
        } else {//一样的就取最低价格
            price = retailPrice.stripTrailingZeros().toPlainString();
        }


        //获取物流说明
        data.put("logisticsInstructions", logisticsService.getLogisticsInstructions());
        //获取不发货地区
        Callable<List<DtsNoDeliveryRegion>> noDeliveryRegionCallable = () -> logisticsService.getNoDeliveryRegionList(null);
        FutureTask<List<DtsNoDeliveryRegion>> noDeliveryRegionListTask = new FutureTask<>(noDeliveryRegionCallable);
        executorService.submit(noDeliveryRegionListTask);
        try {
            //不发货地区集合
            data.put("noDeliveryRegionList", noDeliveryRegionListTask.get());
        } catch (Exception e) {
            logger.error("获取物流信息出错,商品id:{},msg:{}", goodsId, e.getMessage());
            return ResponseUtil.fail("获取物流信息出错");
        }

        Map<String, Object> infoJson = JSON.parseObject(JSON.toJSONString(info));
        infoJson.put("retailPrice", price);

        data.put("goodsInfo", infoJson);//商品详情
        //是否已收藏该商品
        boolean isCollectFresh = false;
        if (null != userId) {
            int count = collectService.countByTypeAndValueId(userId, CollectTypeEnums.GOODS.getId(), goodsId);
            isCollectFresh = count > 0;
        }
        //获取商品保障列表
        data.put("goodsSecurityList", goodsSecurityService.selectList());
        data.put("isCollectFresh", isCollectFresh);//是否收藏
        data.put("commentCount", commentMapperEx.getCommentListByGoodsIdCount(goodsId));//商品评论总数
        if (null != userId) {
            //异步添加用户足迹
            DtsUserFootprint userFootprint = new DtsUserFootprint();
            userFootprint.setUserId(userId);
            userFootprint.setGoodsId(goodsId);
            userFootprint.setAddTime(LocalDateTime.now());
            wxAsyncFactory.asyncAddFootprint(userFootprint);
        }

        return ResponseUtil.ok(data);
    }



    /**
     * 商品详情
     *
     * @param userId
     * @param goodsId
     * @return
     */
    public Object detailByGroup(Integer userId, Integer goodsId, Integer groupId) {
        DtsUser user = null != userId ? userService.findById(userId) : null;

        // 商品信息
        DtsGoods info = goodsService.selectById(goodsId);
        if (null == info) {
            return ResponseUtil.badArgument("商品不存在或已下架");
        }

        DtsGroupProduct groupProduct = groupProductService.getGroupProduct(groupId);

        // 商品规格对应的数量和价格
        Callable<List<DtsGoodsProductService.specificationVo>> goodsProductsCallable = () -> productService.getGoodsProduct(goodsId,user,false, groupProduct);
        FutureTask<List<DtsGoodsProductService.specificationVo>> goodsProductsListTask = new FutureTask<>(goodsProductsCallable);
        executorService.submit(goodsProductsListTask);
        Map<String, Object> data = new HashMap<>();
        try {
            data.put("productList", goodsProductsListTask.get());//货品集合
        } catch (Exception e) {
            logger.error("获取商品规格出错-商品规格,商品id:{},msg:{}", goodsId, e.getMessage());
            return ResponseUtil.fail("获取商品规格出错");
        }


        //商品最低价格
        BigDecimal retailPrice = info.getRetailPrice();

        String price = null;

        //商品最高价格
        BigDecimal maxPrice = goodsService.getGoodsMaxPrice(goodsId);
        if (!StringUtils.equals(retailPrice.toString(), maxPrice.toString())) {//最高价格和最低价格不一样就拼接价格范围
            price = retailPrice.stripTrailingZeros().toPlainString() + "～" + maxPrice.stripTrailingZeros().toPlainString();
        } else {//一样的就取最低价格
            price = retailPrice.stripTrailingZeros().toPlainString();
        }


        //获取物流说明
        data.put("logisticsInstructions", logisticsService.getLogisticsInstructions());
        //获取不发货地区
        Callable<List<DtsNoDeliveryRegion>> noDeliveryRegionCallable = () -> logisticsService.getNoDeliveryRegionList(null);
        FutureTask<List<DtsNoDeliveryRegion>> noDeliveryRegionListTask = new FutureTask<>(noDeliveryRegionCallable);
        executorService.submit(noDeliveryRegionListTask);
        try {
            //不发货地区集合
            data.put("noDeliveryRegionList", noDeliveryRegionListTask.get());
        } catch (Exception e) {
            logger.error("获取物流信息出错,商品id:{},msg:{}", goodsId, e.getMessage());
            return ResponseUtil.fail("获取物流信息出错");
        }

        Map<String, Object> infoJson = JSON.parseObject(JSON.toJSONString(info));
        infoJson.put("retailPrice", price);

        if(user!= null){
            data.put("vipType", user.getVipType());//商品详情
        }
        data.put("goodsInfo", infoJson);//商品详情
        data.put("groupInfo", groupProduct);//商品详情
        //是否已收藏该商品
        boolean isCollectFresh = false;
        if (null != userId) {
            int count = collectService.countByTypeAndValueId(userId, CollectTypeEnums.GOODS.getId(), goodsId);
            isCollectFresh = count > 0;
        }
        //获取商品保障列表
        data.put("goodsSecurityList", goodsSecurityService.selectList());
        data.put("isCollectFresh", isCollectFresh);//是否收藏
        data.put("commentCount", commentMapperEx.getCommentListByGoodsIdCount(goodsId));//商品评论总数
        if (null != userId) {
            //异步添加用户足迹
            DtsUserFootprint userFootprint = new DtsUserFootprint();
            userFootprint.setUserId(userId);
            userFootprint.setGoodsId(goodsId);
            userFootprint.setAddTime(LocalDateTime.now());
            wxAsyncFactory.asyncAddFootprint(userFootprint);
        }

        return ResponseUtil.ok(data);
    }


    /**
     * 商品评论列表
     *
     * @param goodsId
     * @param page
     * @param size
     * @return
     */
    public TableDataInfo getCommentList(Integer goodsId, Integer page, Integer size) {
        Page p = PageHelper.startPage(page, size);
        List<WxGoodsCommentVo> list = commentMapperEx.getCommentListByGoodsId(goodsId);
        if (CollectionUtils.isEmpty(list)) {
            list = new ArrayList<>();
        } else {
            list.forEach(item -> {
                item.setCommentUserId(null);
            });
        }
        return TableDataInfo.getDataTable(list, p.getTotal());
    }

}
